summaryrefslogtreecommitdiff
path: root/app/[lng]/evcp
diff options
context:
space:
mode:
Diffstat (limited to 'app/[lng]/evcp')
-rw-r--r--app/[lng]/evcp/(evcp)/b-rfq/page.tsx3
-rw-r--r--app/[lng]/evcp/(evcp)/evaluation-check-list/page.tsx18
-rw-r--r--app/[lng]/evcp/(evcp)/evaluation-target-list/page.tsx65
-rw-r--r--app/[lng]/evcp/(evcp)/evaluation/page.tsx19
-rw-r--r--app/[lng]/evcp/(evcp)/system/layout.tsx11
-rw-r--r--app/[lng]/evcp/(evcp)/system/password-policy/page.tsx63
6 files changed, 98 insertions, 81 deletions
diff --git a/app/[lng]/evcp/(evcp)/b-rfq/page.tsx b/app/[lng]/evcp/(evcp)/b-rfq/page.tsx
index 213e9127..a66d7b58 100644
--- a/app/[lng]/evcp/(evcp)/b-rfq/page.tsx
+++ b/app/[lng]/evcp/(evcp)/b-rfq/page.tsx
@@ -46,6 +46,8 @@ export default async function PQReviewPage(props: PQReviewPageProps) {
})
])
+ console.log(search, "견적")
+
return (
<Shell className="gap-4">
<div className="flex items-center justify-between space-y-2">
@@ -60,7 +62,6 @@ export default async function PQReviewPage(props: PQReviewPageProps) {
{/* Items처럼 직접 테이블 렌더링 */}
<React.Suspense
- key={JSON.stringify(searchParams)} // URL 파라미터가 변경될 때마다 강제 리렌더링
fallback={
<DataTableSkeleton
columnCount={8}
diff --git a/app/[lng]/evcp/(evcp)/evaluation-check-list/page.tsx b/app/[lng]/evcp/(evcp)/evaluation-check-list/page.tsx
index 398005fa..a660c492 100644
--- a/app/[lng]/evcp/(evcp)/evaluation-check-list/page.tsx
+++ b/app/[lng]/evcp/(evcp)/evaluation-check-list/page.tsx
@@ -32,6 +32,24 @@ async function EvaluationCriteriaPage(props: EvaluationCriteriaPageProps) {
return (
<Shell className="gap-2">
+ <div className="flex items-center justify-between space-y-2">
+ <div className="flex items-center justify-between space-y-2">
+ <div>
+ <h2 className="text-2xl font-bold tracking-tight">
+ 협력업체 평가기준표
+ </h2>
+ <p className="text-muted-foreground">
+ 협력업체 평가에 사용되는 평가기준표를 관리{" "}
+ {/* <span className="inline-flex items-center whitespace-nowrap">
+ <Ellipsis className="size-3" />
+ <span className="ml-1">버튼</span>
+ </span>
+ 을 통해 담당자 연락처, 입찰 이력, 계약 이력, 패키지 내용 등을 확인 할 수 있습니다. */}
+ </p>
+ </div>
+ </div>
+ </div>
+
<Suspense fallback={<Skeleton className="h-7 w-52" />}>
{/* <DateRangePicker
triggerSize="sm"
diff --git a/app/[lng]/evcp/(evcp)/evaluation-target-list/page.tsx b/app/[lng]/evcp/(evcp)/evaluation-target-list/page.tsx
index d60f695a..088ae75b 100644
--- a/app/[lng]/evcp/(evcp)/evaluation-target-list/page.tsx
+++ b/app/[lng]/evcp/(evcp)/evaluation-target-list/page.tsx
@@ -26,66 +26,7 @@ interface EvaluationTargetsPageProps {
searchParams: Promise<SearchParams>
}
-// 프로세스 안내 팝오버 컴포넌트
-function ProcessGuidePopover() {
- return (
- <Popover>
- <PopoverTrigger asChild>
- <Button variant="ghost" size="icon" className="h-6 w-6">
- <HelpCircle className="h-4 w-4 text-muted-foreground" />
- </Button>
- </PopoverTrigger>
- <PopoverContent className="w-96" align="start">
- <div className="space-y-3">
- <div className="space-y-1">
- <h4 className="font-medium">평가 대상 확정 프로세스</h4>
- <p className="text-sm text-muted-foreground">
- 발주실적을 기반으로 평가 대상을 확정하는 절차입니다.
- </p>
- </div>
- <div className="space-y-3 text-sm">
- <div className="flex gap-3">
- <div className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
- 1
- </div>
- <div>
- <p className="font-medium">발주실적 기반 자동 추출</p>
- <p className="text-muted-foreground">전년도 10월 ~ 해당년도 9월 발주실적에서 업체 목록을 자동으로 생성합니다.</p>
- </div>
- </div>
- <div className="flex gap-3">
- <div className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
- 2
- </div>
- <div>
- <p className="font-medium">담당자 지정</p>
- <p className="text-muted-foreground">각 평가 대상별로 5개 부서(발주/조달/품질/설계/CS)의 담당자를 지정합니다.</p>
- </div>
- </div>
- <div className="flex gap-3">
- <div className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
- 3
- </div>
- <div>
- <p className="font-medium">검토 및 의견 수렴</p>
- <p className="text-muted-foreground">모든 담당자가 평가 대상 적합성을 검토하고 의견을 제출합니다.</p>
- </div>
- </div>
- <div className="flex gap-3">
- <div className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
- 4
- </div>
- <div>
- <p className="font-medium">최종 확정</p>
- <p className="text-muted-foreground">모든 담당자 의견이 일치하면 평가 대상으로 최종 확정됩니다.</p>
- </div>
- </div>
- </div>
- </div>
- </PopoverContent>
- </Popover>
- )
-}
+
export default async function EvaluationTargetsPage(props: EvaluationTargetsPageProps) {
const searchParams = await props.searchParams
@@ -131,7 +72,7 @@ export default async function EvaluationTargetsPage(props: EvaluationTargetsPage
<Badge variant="outline" className="text-sm">
{currentEvaluationYear}년도
</Badge>
- <ProcessGuidePopover />
+
</div>
</div>
</div>
@@ -162,10 +103,12 @@ export default async function EvaluationTargetsPage(props: EvaluationTargetsPage
/>
}
>
+ {currentEvaluationYear &&
<EvaluationTargetsTable
promises={promises}
evaluationYear={currentEvaluationYear}
/>
+}
</React.Suspense>
</Shell>
)
diff --git a/app/[lng]/evcp/(evcp)/evaluation/page.tsx b/app/[lng]/evcp/(evcp)/evaluation/page.tsx
index 3ae3272a..ead61077 100644
--- a/app/[lng]/evcp/(evcp)/evaluation/page.tsx
+++ b/app/[lng]/evcp/(evcp)/evaluation/page.tsx
@@ -17,6 +17,8 @@ import {
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { PeriodicEvaluationsTable } from "@/lib/evaluation/table/evaluation-table"
+import { getPeriodicEvaluations } from "@/lib/evaluation/service"
+import { searchParamsEvaluationsCache } from "@/lib/evaluation/validation"
export const metadata: Metadata = {
title: "협력업체 정기평가",
@@ -93,25 +95,11 @@ function getDefaultEvaluationYear() {
return new Date().getFullYear()
}
-function searchParamsPeriodicEvaluationsCache() {
- // TODO: 실제 파서 구현
- return {
- parse: (params: any) => params
- }
-}
-async function getPeriodicEvaluations(params: any) {
- // TODO: 실제 API 호출 구현
- return {
- data: [],
- total: 0,
- pageCount: 0
- }
-}
export default async function PeriodicEvaluationsPage(props: PeriodicEvaluationsPageProps) {
const searchParams = await props.searchParams
- const search = searchParamsPeriodicEvaluationsCache().parse(searchParams)
+ const search = searchParamsEvaluationsCache.parse(searchParams)
const validFilters = getValidFilters(search.filters || [])
// 기본 필터 처리
@@ -150,7 +138,6 @@ export default async function PeriodicEvaluationsPage(props: PeriodicEvaluations
<Badge variant="outline" className="text-sm">
{currentEvaluationYear}년도
</Badge>
- <ProcessGuidePopover />
</div>
</div>
</div>
diff --git a/app/[lng]/evcp/(evcp)/system/layout.tsx b/app/[lng]/evcp/(evcp)/system/layout.tsx
index 62f3e845..7e8f69d0 100644
--- a/app/[lng]/evcp/(evcp)/system/layout.tsx
+++ b/app/[lng]/evcp/(evcp)/system/layout.tsx
@@ -28,7 +28,7 @@ export default async function SettingsLayout({
const sidebarNavItems = [
{
- title: "SHI Users",
+ title: "삼성중공업 사용자",
href: `/${lng}/evcp/system`,
},
{
@@ -36,13 +36,18 @@ export default async function SettingsLayout({
href: `/${lng}/evcp/system/roles`,
},
{
- title: "Permissions",
+ title: "권한 통제",
href: `/${lng}/evcp/system/permissions`,
},
{
- title: "Vendor Users",
+ title: "협력업체 사용자",
href: `/${lng}/evcp/system/admin-users`,
},
+
+ {
+ title: "비밀번호 정책",
+ href: `/${lng}/evcp/system/password-policy`,
+ },
]
diff --git a/app/[lng]/evcp/(evcp)/system/password-policy/page.tsx b/app/[lng]/evcp/(evcp)/system/password-policy/page.tsx
new file mode 100644
index 00000000..0f14fefe
--- /dev/null
+++ b/app/[lng]/evcp/(evcp)/system/password-policy/page.tsx
@@ -0,0 +1,63 @@
+// app/admin/password-policy/page.tsx
+
+import * as React from "react"
+import { Skeleton } from "@/components/ui/skeleton"
+import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
+import { Separator } from "@/components/ui/separator"
+import { Alert, AlertDescription } from "@/components/ui/alert"
+import { AlertTriangle } from "lucide-react"
+import SecuritySettingsTable from "@/components/system/passwordPolicy"
+import { getSecuritySettings } from "@/lib/password-policy/service"
+
+
+export default async function PasswordPolicyPage() {
+ try {
+ // 보안 설정 데이터 로드
+ const securitySettings = await getSecuritySettings()
+
+ return (
+ <React.Suspense
+ fallback={
+ <DataTableSkeleton
+ columnCount={4}
+ searchableColumnCount={0}
+ filterableColumnCount={0}
+ cellWidths={["20rem", "30rem", "15rem", "10rem"]}
+ shrinkZero
+ />
+ }
+ >
+ <div className="space-y-6">
+ <div>
+ <h3 className="text-lg font-medium">협력업체 사용자 비밀번호 정책 설정</h3>
+ <p className="text-sm text-muted-foreground">
+ 협력업체 사용자들을 위한 비밀번호 정책과 보안 설정을 관리할 수 있습니다.
+ </p>
+ </div>
+ <Separator />
+ <SecuritySettingsTable initialSettings={securitySettings} />
+ </div>
+ </React.Suspense>
+ )
+ } catch (error) {
+ console.error('Failed to load security settings:', error)
+
+ return (
+ <div className="space-y-6">
+ <div>
+ <h3 className="text-lg font-medium">협력업체 사용자 비밀번호 정책 설정</h3>
+ <p className="text-sm text-muted-foreground">
+ 협력업체 사용자들을 위한 비밀번호 정책과 보안 설정을 관리할 수 있습니다.
+ </p>
+ </div>
+ <Separator />
+ <Alert variant="destructive">
+ <AlertTriangle className="h-4 w-4" />
+ <AlertDescription>
+ 보안 설정을 불러오는 중 오류가 발생했습니다. 페이지를 새로고침하거나 관리자에게 문의하세요.
+ </AlertDescription>
+ </Alert>
+ </div>
+ )
+ }
+} \ No newline at end of file